﻿using System.Collections.Generic;
using IQIGame.Onigao.Framework;
using IQIGame.Onigao.Framework.Serialization;
using IQIGame.Onigao.Game;
using IQIGame.Onigao.GamePlay;
using LFloatMath.Math;
using NetProtocol.POD;


namespace IQIGame.Onigao.Logic
{
    public class SkillEffective_Summon : SkillEffective
    {
        protected override ISerializeCustomPOD OnExecute(SkillEffectiveData data, Unit target, SkillEffectiveContext context, int effectiveIndex, out SkillEffectiveResponse startResp)
        {
            startResp = null;
            return this.Execute(data.effectiveConfig.customConfig, target, context);
        }

        protected override ISerializeCustomPOD OnActionExecute(SkillEffectiveData data, SkillActionNode action, Unit target, ref SkillEffectiveContext context, int effectiveIndex)
        {
            return this.Execute(action.customConfig, target, context);
        }

        private ISerializeCustomPOD Execute(SkillCustomConfig rCustomConfig, Unit rTarget, SkillEffectiveContext rContext)
        {
            if (rCustomConfig is SkillEffectiveAction_Summon_ConfigData rConfig)
            {
                var rSelf = rContext.skill.executer;
                if (rSelf.summon.Count >= rConfig.maxCount)
                {
                    return null;
                }

                var rPlayCtrl = rSelf.battle.playCtrl;
                var rMapCtrl = rPlayCtrl.mapCtrl;

                var rReferPos = rTarget.pos;
                var rReferAspect = rTarget.forward;
                var fReferRadius = rTarget.radius;
                var nReferTeam = rSelf.teamIndex;
                var rPos = new LVector2(new LFloat(true, rConfig.posX), new LFloat(true, rConfig.posY));
                if (rPos != LVector2.zero)
                {
                    // 根据当前朝向计算相对位置 （默认 （0，1））
                    var rTheta = LMath.AngleInt(rReferAspect.ToLVector3XZ(LFloat.zero), LVector3.forward);
                    if (rReferAspect.x > 0) // 将弧度计算转为逆时针的
                    {
                        rTheta = (2 * LFloat.PI) - rTheta;
                    }
                    var fCos = LMath.Cos(rTheta);
                    var fSin = LMath.Sin(rTheta);
                    rPos = new LVector2(
                        rPos.x * fCos - rPos.y * fSin,
                        rPos.x * fSin + rPos.y * fCos
                    );
                }
                var rTargetPos = rReferPos + rPos;
                if (rMapCtrl.MapCanUse(0, rTargetPos, fReferRadius) || rMapCtrl.GetMapCanUse(rTargetPos, fReferRadius, out rTargetPos)) // 位置
                {
                    var rAttrType = ListPool<int>.Get();
                    var rAttrValue = ListPool<int>.Get();
                    UnitFactory.GetMonsterPanelAttr(rConfig.power, rConfig.powerType, rConfig.attrCorr, ref rAttrType, ref rAttrValue, out int nWeakNum);

                    var rMonsterConfig = TableCenter.monster.Get(rConfig.monsterID);
                    // 转二进制
                    var rWeakType = EDamageType.None;
                    for (int k = 0; k < rMonsterConfig.WeakType.Count; k++)
                    {
                        rWeakType |= (EDamageType)(1 << rMonsterConfig.WeakType[k]);
                    }
                    // 创建单位
                    var rUnit = UnitFactory.CreateBattleUnit(rPlayCtrl.battle, rConfig.monsterID, nReferTeam, EUnitType.Monster,
                        rMonsterConfig.Radius.ToLFloat() / LFloat.hundred, rTargetPos, rReferAspect, rAttrType, rAttrValue, rMonsterConfig.Skill,
                        true, rMonsterConfig.AI, nWeakNum, rWeakType, new List<int>(rMonsterConfig.SideAngle), new List<int>(rMonsterConfig.BackAngle));

                    rPlayCtrl.unitCtrl.AddUnit(rUnit);
                    rSelf.summon.Add(rUnit);

                    ListPool<int>.Put(rAttrType);
                    ListPool<int>.Put(rAttrValue);

                    // 修正特殊属性
                    var rAttr = rUnit.GetComponent<AttributeComponent>(ETComponentType.AttributeComponent);
                    var rSelfAttr = rSelf.GetComponent<AttributeComponent>(ETComponentType.AttributeComponent);
                    for (int i = 0; i < rConfig.specialAttr.Count; i++)
                    {
                        var rSpecialAttr = rConfig.specialAttr[i];
                        var rFlagType = rSpecialAttr.attrType;
                        var fRate = rSpecialAttr.attrRate;
                        var nFormula = rSpecialAttr.formula;
                        for (int j = (int)EAttributeType.Min; j < (int)EAttributeType.Max; j++)
                        {
                            if (((int)rFlagType & (1 << j)) != 0)
                            {
                                var rType = (EAttributeType)j;
                                LFloat nReferAttrValue;
                                if (nFormula == 0)
                                {
                                    nReferAttrValue = fRate * rSelfAttr.Get(rType);
                                }
                                else
                                {
                                    nReferAttrValue = Formula.Calculate<LFloat>(nFormula, rSelf, rUnit);
                                }
                                rAttr.Set(rType, LMath.Round(nReferAttrValue).ToInt());
                            }
                        }
                    }

                    var rResp = ClassPool.Get<SummonResponse>();
                    // rResp.config = rConfig;
                    // rResp.pos = rTargetPos;
                    // rResp.forward = rReferAspect;
                    rResp.SetUnit(rUnit, rSelf);
                    return rResp;
                }
            }
            return null;
        }

#if UNITY_EDITOR
        public override string ToString(SkillCustomConfig config)
        {
            var rConfig = config as SkillEffectiveAction_Summon_ConfigData;
            return $"召唤 {rConfig?.monsterID}";
        }
#endif
    }
}